package com.integration.maven.service2controllerProcessor.processor;

import com.google.auto.service.AutoService;
import com.integration.maven.service2controllerProcessor.annotation.*;
import com.squareup.javapoet.*;
import com.sun.tools.javac.api.JavacTrees;
import com.sun.tools.javac.code.Attribute;
import com.sun.tools.javac.code.Symbol;
import com.sun.tools.javac.model.JavacElements;
import com.sun.tools.javac.processing.JavacProcessingEnvironment;
import com.sun.tools.javac.tree.JCTree;
import com.sun.tools.javac.tree.TreeMaker;
import com.sun.tools.javac.util.Context;
import com.sun.tools.javac.util.Name;
import com.sun.tools.javac.util.Names;
import com.sun.tools.javac.util.Pair;
import io.swagger.annotations.ApiModelProperty;

import javax.annotation.processing.*;
import javax.lang.model.SourceVersion;
import javax.lang.model.element.Element;
import javax.lang.model.element.ElementKind;
import javax.lang.model.element.Modifier;
import javax.lang.model.element.TypeElement;
import javax.lang.model.type.MirroredTypeException;
import javax.tools.Diagnostic;
import java.io.IOException;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.*;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * @Author ckk
 * @Date 2020/12/24 9:41
 * @Description 功能描述: APT
 **/
//  声明处理的 注解
@SupportedAnnotationTypes({"com.integration.maven.service2controllerProcessor.annotation.Service2RestController",
        "com.integration.maven.service2controllerProcessor.annotation.Service2FeignClient"})
//  jdk8 以上
@SupportedSourceVersion(SourceVersion.RELEASE_8)
//  自动添加配置文件
@AutoService(Processor.class)
public class Service2ControllerProcessor extends AbstractProcessor {


    private JavacTrees trees;
    private TreeMaker treeMaker;
    private Names names;
    // 打印信息使用
    private Messager messager;
    private JavacElements elementUtils;
    private static final String handlePath = "com.integration.maven.service2controllerProcessor.handle";


    @Override
    public synchronized void init(ProcessingEnvironment processingEnv) {
        super.init(processingEnv);
        this.trees = JavacTrees.instance(processingEnv);
        Context context = ((JavacProcessingEnvironment) processingEnv).getContext();
        this.treeMaker = TreeMaker.instance(context);
        this.names = Names.instance(context);
        messager = processingEnv.getMessager();
        // messager.printMessage(Diagnostic.Kind.NOTE, "1------------------------------------");
        // 从 Element 转 tree 的工具
        elementUtils = (JavacElements) processingEnv.getElementUtils();
    }

    @Override
    public boolean process(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv) {


        // 循环Service2RestController注解元素
        for (Element element : roundEnv.getElementsAnnotatedWith(Service2RestController.class)) {
            // 判断是类是接口才需要处理
            if (element.getKind() == ElementKind.INTERFACE) {
                // 转化元素到类
                TypeElement typeElement = (TypeElement) element;
                // 获取注解
                Service2RestController service2RestController = element.getAnnotation(Service2RestController.class);
                // 生成controller 类名
                String className = "";
                // 如果是 xxxxService 转化 XXXXController
                if (typeElement.getSimpleName().toString().endsWith("Service")) {
                    className = typeElement.getSimpleName().toString().replace("Service", "Controller");
                } else {
                    // 如果是 xxxx 转化 XXXXController
                    className = typeElement.getSimpleName().toString() + "Controller";
                }
                // 创建controller类
                TypeSpec typeSpec = generateControllerClass(className,
                        element, service2RestController.ignorePrefixAnnotation(), service2RestController.name(), roundEnv);
                if (typeSpec == null) {
                    continue;
                }
                //生成包名
                String PackageName = typeElement.getQualifiedName().toString().substring(0, typeElement.getQualifiedName().toString().lastIndexOf("."));
                // 生成java文件
                JavaFile javaFile = JavaFile.builder(PackageName + ".controller", typeSpec).
                        build();
                try {
                    // 写出新的文件
                    javaFile.writeTo(processingEnv.getFiler());
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }

        // 循环Service2FeignClient注解元素
        for (Element element : roundEnv.getElementsAnnotatedWith(Service2FeignClient.class)) {
            // 判断是类是接口才需要处理
            if (element.getKind() == ElementKind.INTERFACE) {
                // 转化元素到类
                TypeElement typeElement = (TypeElement) element;
                // 获取注解
                Service2FeignClient service2FeignClient = element.getAnnotation(Service2FeignClient.class);
                // 生成 feign 名称
                String className = "";
                // 如果是 xxxxService 转化 XXXXController
                if (typeElement.getSimpleName().toString().endsWith("Service")) {
                    className = typeElement.getSimpleName().toString().replace("Service", "Feign");
                } else {
                    // 如果是 xxxx 转化 XXXXController
                    className = typeElement.getSimpleName().toString() + "Feign";
                }
                // 创建Feign类
                TypeSpec typeSpec = generateFeignClass(className,
                        element, service2FeignClient.ignorePrefixAnnotation(), service2FeignClient.name(), roundEnv);
                if (typeSpec == null) {
                    continue;
                }
                //生成包名
                String PackageName = typeElement.getQualifiedName().toString().substring(0, typeElement.getQualifiedName().toString().lastIndexOf("."));
                // 生成java文件
                JavaFile javaFile = JavaFile.builder(PackageName + ".feign", typeSpec).
                        build();
                try {
                    // 写出新的文件
                    javaFile.writeTo(processingEnv.getFiler());
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }

        return true;
    }


    /**
     * 创建类
     *
     * @param classes  类名称
     * @param element
     * @param roundEnv
     * @return
     */
    private TypeSpec generateControllerClass(String classes, Element element, String[] ignoreAnnotation, String serviceName,
                                             RoundEnvironment roundEnv) {

        // 接口类型
        if (element.getKind() == ElementKind.INTERFACE) {
            // element 是类元素
            TypeElement typeElement = (TypeElement) element;
            //  初始化新的类  classes 类名
            TypeSpec.Builder builder = TypeSpec.classBuilder(classes)
                    // public 修饰符
                    .addModifiers(Modifier.PUBLIC);
            // 获取类上面的注解列表
            List<AnnotationSpec> list = getAnnotationMirrors2AnnotationSpecList((List<Attribute.Compound>) typeElement.getAnnotationMirrors(),
                    ignoreAnnotation, true, serviceName);
            // 将注解添加到创建的类上面
            builder.addAnnotations(list);
            // 获取当前类的包名
            String PackageName = typeElement.getQualifiedName().toString().substring(0, typeElement.getQualifiedName().toString().lastIndexOf("."));
            // 获取当前类 service
            ClassName serviceClass = ClassName.get(PackageName, typeElement.getSimpleName().toString());
            // 添加service
            builder.addField(FieldSpec.builder(serviceClass, typeElement.getSimpleName().toString().substring(0, 1).toLowerCase() + typeElement.getSimpleName().toString().substring(1))
                    // public 修饰符
                    .addModifiers(Modifier.PRIVATE)
                    // 添加 @Autowired xxxxService
                    .addAnnotation(AnnotationSpec.builder(ClassName.get("org.springframework.beans.factory.annotation", "Autowired"))
                            // 设置Autowired注解属性  required = false
                            .addMember("required", "$L", false)
                            .build())
                    .build());
            // 添加 SecurityDataHandle
            ClassName SecurityDataHandleClass = ClassName.get(handlePath, "SecurityDataHandle");
            builder.addField(FieldSpec.builder(SecurityDataHandleClass, "securityDataHandle")
                    // public 修饰符
                    .addModifiers(Modifier.PRIVATE)
                    // 添加 @Autowired xxxxService
                    .addAnnotation(AnnotationSpec.builder(ClassName.get("org.springframework.beans.factory.annotation", "Autowired"))
                            // 设置Autowired注解属性  required = false
                            .addMember("required", "$L", false)
                            .build())
                    .build());
            // 添加 ResponseHandle
            ClassName ResponseHandleClass = ClassName.get(handlePath, "ResponseHandle");
            builder.addField(FieldSpec.builder(ResponseHandleClass, "responseHandle")
                    // public 修饰符
                    .addModifiers(Modifier.PRIVATE)
                    // 添加 @Autowired xxxxService
                    .addAnnotation(AnnotationSpec.builder(ClassName.get("org.springframework.beans.factory.annotation", "Autowired"))
                            // 设置Autowired注解属性  required = false
                            .addMember("required", "$L", false)
                            .build())
                    .build());
            // 获取节点
            List<? extends Element> enclosedElements = typeElement.getEnclosedElements();
            // 循环节点
            for (Element e : enclosedElements) {
                // 方法
                if (e.getKind() == ElementKind.METHOD) {
                    // 转化 方法
                    Symbol.MethodSymbol symbol = (Symbol.MethodSymbol) e;

                    Exposes exposes = symbol.getAnnotation(Exposes.class);
                    if (exposes != null) {
                        for (Expose expose : exposes.value()) {
                            // 创建Mapping方法
                            MethodSpec methodSpec = makeMappingControllerMethod(element, symbol, ignoreAnnotation,
                                    true, serviceName, expose);
                            if (methodSpec != null) {
                                // 添加到新的类中
                                builder.addMethod(methodSpec);
                            }
                        }
                    } else {
                        Expose expose = symbol.getAnnotation(Expose.class);
                        if (expose != null) {
                            // 创建Mapping方法
                            MethodSpec methodSpec = makeMappingControllerMethod(element, symbol, ignoreAnnotation,
                                    true, serviceName, expose);
                            if (methodSpec != null) {
                                // 添加到新的类中
                                builder.addMethod(methodSpec);
                            }
                        }
                    }

                }
            }
            // 生成类
            return builder.build();
        }
        return null;
    }


    /**
     * 创建类
     *
     * @param classes  类名称
     * @param element
     * @param roundEnv
     * @return
     */
    private TypeSpec generateFeignClass(String classes, Element element, String[] ignoreAnnotation, String serviceName, RoundEnvironment roundEnv) {
        // 接口类型
        if (element.getKind() == ElementKind.INTERFACE) {
            // element 是类元素
            TypeElement typeElement = (TypeElement) element;
            //  初始化新的类
            TypeSpec.Builder builder = TypeSpec.interfaceBuilder(classes)
                    // public 修饰符
                    .addModifiers(Modifier.PUBLIC);
            // 获取类上面的注解列表
            List<AnnotationSpec> list = getAnnotationMirrors2AnnotationSpecList((List<Attribute.Compound>) typeElement.getAnnotationMirrors(),
                    ignoreAnnotation, false, serviceName);
            builder.addAnnotations(list);
            // 获取节点
            List<? extends Element> enclosedElements = typeElement.getEnclosedElements();
            // 循环节点
            for (Element e : enclosedElements) {
                // 方法
                if (e.getKind() == ElementKind.METHOD) {
                    // 转化 方法
                    Symbol.MethodSymbol symbol = (Symbol.MethodSymbol) e;
                    Exposes exposes = symbol.getAnnotation(Exposes.class);
                    if (exposes != null) {
                        for (Expose expose : exposes.value()) {
                            if(expose.type() == ApiTypeEnum.feign){
                                // 创建Mapping方法
                                MethodSpec methodSpec = makeMappingFeignMethod(element, symbol, ignoreAnnotation,
                                        true, serviceName, expose);
                                if (methodSpec != null) {
                                    // 添加到新的类中
                                    builder.addMethod(methodSpec);
                                }
                            }

                        }
                    } else {
                        Expose expose = symbol.getAnnotation(Expose.class);
                        if (expose != null) {
                            if(expose.type() == ApiTypeEnum.feign) {
                                // 创建Mapping方法
                                MethodSpec methodSpec = makeMappingFeignMethod(element, symbol, ignoreAnnotation,
                                        true, serviceName, expose);
                                if (methodSpec != null) {
                                    // 添加到新的类中
                                    builder.addMethod(methodSpec);
                                }
                            }
                        }
                    }
                }
            }
            // 生成类
            return builder.build();
        }
        return null;
    }


    /**
     * 获取Dto注解并生成对应的注释
     */
    private Map<String, String> getDtoClassNotes(List<Symbol.VarSymbol> parameters, JCTree.JCClassDecl classDecl) {
        // 存储注解
        Map<String, String> notesMap = new HashMap<>();
        // 获取节点列表
        List<JCTree> jcTrees = classDecl.defs;
        // 循环节点
        for (JCTree jcTree : jcTrees) {
            // 判断是属性节点
            if (jcTree instanceof JCTree.JCVariableDecl) {
                // 强制转化属性节点
                JCTree.JCVariableDecl variableDecl = (JCTree.JCVariableDecl) jcTree;
                // 获取属性的注解
                List<JCTree.JCAnnotation> annotations = variableDecl.getModifiers().getAnnotations();
                boolean isNeed = false;
                boolean isContinue = false;
                for (Symbol.VarSymbol p_one : parameters) {
                    if (p_one.name.toString().equals(variableDecl.getName().toString())) {
                        isNeed = true;
                        SecurityData securityData = p_one.getAnnotation(SecurityData.class);
                        if (securityData != null) {
                            isContinue = true;
                        }
                    }
                }
                if (isContinue) {
                    continue;
                }
                if (isNeed) {
                    // 循环注解
                    for (JCTree.JCAnnotation a_one : annotations) {
                        // 必须是 ApiModelProperty 注解
                        if (a_one.type.toString().endsWith("ApiModelProperty")) {
                            // 获取 ApiModelProperty 里面的 键值对
                            Map<String, String> map = getAnnotationValues(a_one);
                            String r = map.get("value");
                            if (r != null) {
                                // 添加注解列表
                                notesMap.put(variableDecl.getName().toString(), convertUnicodeToCh(r));
                            }
                        }
                    }
                }
            }
        }
        // 返回注释列表
        return notesMap;
    }

    public Map<String, String> getDtoClassNotes(List<Symbol.VarSymbol> parameters, Class clz) throws Exception {
        // 存储注解
        Map<String, String> notesMap = new HashMap<>();
        //我们项目的所有实体类都继承BaseDomain （所有实体基类：该类只是串行化一下）
        //不需要的自己去掉即可
        if (clz != null) {
            // 拿到该类
            if (clz.getSuperclass() != null) {
                notesMap = getDtoClassNotes(parameters, clz.getSuperclass());
            }
            // 获取实体类的所有属性，返回Field数组
            Field[] fields = clz.getDeclaredFields();

            for (Field field : fields) {// --for() begin
                boolean isNeed = false;
                boolean isContinue = false;
                for (Symbol.VarSymbol p_one : parameters) {
                    if (p_one.name.toString().equals(field.getName().toString())) {
                        isNeed = true;
                        SecurityData securityData = p_one.getAnnotation(SecurityData.class);
                        if (securityData != null) {
                            isContinue = true;
                        }
                    }
                }
                if (isContinue) {
                    continue;
                }
                if (isNeed) {
                    ApiModelProperty a = field.getAnnotation(ApiModelProperty.class);
                    if (a != null) {
                        // 添加注解列表
                        notesMap.put(field.getName(), a.value());
                    }
                }
            }
        }
        // 返回注释列表
        return notesMap;
    }

    /**
     * 获取注解的值map
     */
    private Map<String, String> getAnnotationValues(JCTree.JCAnnotation annotation) {
        // 获取注解的表达式
        List<JCTree.JCExpression> arguments = annotation.getArguments();
        // 存储键值对
        Map<String, String> map = new HashMap<>();
        // 循环表达式
        for (JCTree.JCExpression one : arguments) {
            // 键名
            String s_one = one.toString().substring(0, one.toString().indexOf("=")).trim();
            // 值
            String s_two = one.toString().substring(one.toString().indexOf("=") + 1).trim();
            // 存储
            map.put(s_one, s_two);
        }
        // 返回
        return map;
    }


    /**
     * 生成controller 的 Mapping 方法
     */
    private MethodSpec makeMappingControllerMethod(Element element, Symbol.MethodSymbol methodSymbol,
                                                   String[] ignoreAnnotation, boolean isRest, String serviceName,
                                                   Expose expose) {

        if (element.getKind() == ElementKind.INTERFACE) {
            // element 是类元素
            TypeElement typeElement = (TypeElement) element;

            // 获取方法上@Dto
            String dtoClass = null;
            Boolean dtoRequired = null;
            ClassName dtoClassName = null;
            Map<String, String> noteMap = null;
            // 参数列表
            List<Symbol.VarSymbol> parameters = methodSymbol.getParameters();
            try {
                // 获取注解
                Dto dto = methodSymbol.getAnnotation(Dto.class);
                if (dto != null) {
                    // 必定报错，必须从异常中获取对应的值
                    dto.dtoClass();
                }
            } catch (MirroredTypeException ex) {
                // 从异常中获取 dto.dtoClass() 的值
                dtoClass = ex.getTypeMirror().toString();
            }
            // dtoClassName 存在，说明需要转化 dto
            if (dtoClass != null) {
                dtoRequired = methodSymbol.getAnnotation(Dto.class).required();
                try {
                    Symbol.ClassSymbol typeElement1 = elementUtils.getTypeElement(dtoClass);
                    dtoClassName = (ClassName) ClassName.get(typeElement1.type);
                    // 通过类名获取element并转化成JCTree节点
                    JCTree.JCClassDecl classDecl = (JCTree.JCClassDecl) elementUtils.getTree(typeElement1);
                    noteMap = getDtoClassNotes(parameters, classDecl);
                } catch (Exception e) {
                    try {
                        noteMap = getDtoClassNotes(parameters, Class.forName(dtoClass));
                    } catch (Exception exception) {
                        exception.printStackTrace();
                    }
                }
            }

            //
            String methodName = methodSymbol.name.toString();
            methodName = expose.type().name()+methodName.substring(0,1).toUpperCase()+methodName.substring(1);

            // 构建方法
            MethodSpec.Builder builder = MethodSpec.methodBuilder(methodName)
                    // 返回值 -- 结果集
                    .returns(Object.class)
                    // 方法修饰符
                    .addModifiers(Modifier.PUBLIC);

            // 添加注释
            if (noteMap != null) {
                builder.addJavadoc("传递实体参数：\n");
                for (Map.Entry<String, String> note : noteMap.entrySet()) {
                    // 循环添加注解
                    builder.addJavadoc(note.getKey() + " : " + note.getValue() + "  --  \n");
                }

            }

            //方法注解
            List<AnnotationSpec> l_a = getAnnotationMirrors2AnnotationSpecList(methodSymbol.getAnnotationMirrors(),
                    ignoreAnnotation, isRest, serviceName);


            Attribute.Compound c = null;
            for (Attribute.Compound one_annotation : methodSymbol.getAnnotationMirrors()) {
                if (one_annotation.type.toString().contains("Exposes")) {
                    for(Map.Entry<Symbol.MethodSymbol, Attribute> m :  one_annotation.getElementValues().entrySet()){
                        for(Attribute a : ((Attribute.Array)m.getValue()).values){
                            Attribute.Compound compound = (Attribute.Compound) a.getValue();
                            for (Pair<Symbol.MethodSymbol, Attribute> one : compound.values) {
                                if (one.fst.toString().contains("type") ) {
                                    if(expose.type().name().toString().equals(one.snd.getValue().toString())){
                                        c = compound;
                                    }
                                }
                            }
                        }
                    }
                }else if(one_annotation.type.toString().contains("Expose")){
                    c = one_annotation;
                }
            }

            if(c == null){
                return null;
            }
            List<AnnotationSpec> m_a = getAnnotationMirrors2AnnotationSpecList(c, expose);


            builder.addAnnotations(l_a);
            builder.addAnnotations(m_a);

            // 存在dto
            if (dtoClassName != null) {
                // 转化dto参数
                ParameterSpec.Builder namePram = ParameterSpec.builder(dtoClassName, "dto");
                // RequestBody 注解自动加入
                AnnotationSpec.Builder annotationSpec = AnnotationSpec.builder(ClassName.get("org.springframework.web.bind.annotation", "RequestBody"));
                annotationSpec.addMember("required", "$L", dtoRequired);
                // 添加
                namePram.addAnnotation(annotationSpec.build());
                // 添加入参数
                builder.addParameter(namePram.build());


                String bs = "";
                List<Object> pr = new ArrayList<>();
                pr.add(methodSymbol.name.toString());
                for (Symbol.VarSymbol s : parameters) {
                    SecurityData securityData = s.getAnnotation(SecurityData.class);
                    if (bs.length() != 0) {
                        bs += " , ";
                    }
                    if (securityData != null) {
                        bs += "(" + s.type + ")this.securityDataHandle.handle($S, $L)";
                        pr.add(s.name.toString());
                        pr.add(securityData.required());
                    } else {
                        bs += "dto." + getMethodName(s.name) + "()";
                    }

                }
                // 返回
                // 条件判断返回结果
                if (methodSymbol.type.toString().contains("void")) {
                    builder.addStatement(typeElement.getSimpleName().toString().substring(0, 1).toLowerCase() +
                                    typeElement.getSimpleName().toString().substring(1) + ".$N(" + bs + ")",
                            pr.toArray(new Object[]{}));
                    builder.addStatement("return responseHandle.$N()", "handle");

                } else {
                    pr.add(0, "handle");
                    // 返回
                    builder.addStatement("return responseHandle.$N(" +
                                    typeElement.getSimpleName().toString().substring(0, 1).toLowerCase() +
                                    typeElement.getSimpleName().toString().substring(1) + ".$N(" + bs + "))",
                            pr.toArray(new Object[]{}));
                }

            } else {
                // 参数
                // 字段集
                List<Symbol.VarSymbol> params = methodSymbol.getParameters();
                String bs = "";
                List<Object> pr = new ArrayList<>();
                pr.add(methodSymbol.name.toString());
                for (Symbol.VarSymbol one : params) {


                    SecurityData securityData = one.getAnnotation(SecurityData.class);
                    if (bs.length() != 0) {
                        bs += " , ";
                    }
                    if (securityData != null) {
                        bs += "(" + one.type + ")this.securityDataHandle.handle($S, $L)";
                        pr.add(one.name.toString());
                        pr.add(securityData.required());
                    } else {
                        // 字段注解
                        TypeName paramsType = ClassName.get(one.type);
                        ParameterSpec.Builder namePram = ParameterSpec.builder(paramsType, one.name.toString());
                        List<AnnotationSpec> list = getAnnotationMirrors2AnnotationSpecList(one.getAnnotationMirrors(),
                                ignoreAnnotation, isRest, serviceName);
                        namePram.addAnnotations(list);
                        builder.addParameter(namePram.build());
                        bs += one.name;
                    }

                }
                // 调用参数
                // 返回
                // 条件判断返回结果
                if (methodSymbol.type.toString().contains("void")) {
                    builder.addStatement(typeElement.getSimpleName().toString().substring(0, 1).toLowerCase() +
                                    typeElement.getSimpleName().toString().substring(1) + ".$N(" + bs + ")",
                            pr.toArray(new Object[]{}));
                    builder.addStatement("return responseHandle.$N()", "handle");

                } else {
                    pr.add(0, "handle");
                    // 返回
                    builder.addStatement("return responseHandle.$N(" +
                                    typeElement.getSimpleName().toString().substring(0, 1).toLowerCase() +
                                    typeElement.getSimpleName().toString().substring(1) + ".$N(" + bs + "))",
                            pr.toArray(new Object[]{}));
                }
            }

            return builder.build();
        }

        return null;

    }


    private MethodSpec makeMappingFeignMethod(Element element, Symbol.MethodSymbol methodSymbol,
                                              String[] ignoreAnnotation, boolean isRest, String serviceName, Expose expose) {

        if (element.getKind() == ElementKind.INTERFACE) {
            TypeElement typeElement = (TypeElement) element;

            // 获取方法上@Dto
            String dtoClass = null;
            ClassName dtoClassName = null;
            Map<String, String> noteMap = null;
            // 参数列表
            List<Symbol.VarSymbol> parameters = methodSymbol.getParameters();
            try {
                // 获取注解
                Dto dto = methodSymbol.getAnnotation(Dto.class);
                if (dto != null) {
                    // 必定报错，必须从异常中获取对应的值
                    dto.dtoClass();
                }
            } catch (MirroredTypeException ex) {
                // 从异常中获取 dto.dtoClass() 的值
                dtoClass = ex.getTypeMirror().toString();
            }
            // dtoClassName 存在，说明需要转化 dto
            if (dtoClass != null) {
                try {
                    Symbol.ClassSymbol typeElement1 = elementUtils.getTypeElement(dtoClass);
                    dtoClassName = (ClassName) ClassName.get(typeElement1.type);
                    // 通过类名获取element并转化成JCTree节点
                    JCTree.JCClassDecl classDecl = (JCTree.JCClassDecl) elementUtils.getTree(typeElement1);
                    noteMap = getDtoClassNotes(parameters, classDecl);
                } catch (Exception e) {
                    try {
                        noteMap = getDtoClassNotes(parameters, Class.forName(dtoClass));
                    } catch (Exception exception) {
                        exception.printStackTrace();
                    }
                }
            }


            // 构建方法
            MethodSpec.Builder builder = MethodSpec.methodBuilder(methodSymbol.name.toString())
                    // 方法修饰符
                    .addModifiers(Modifier.ABSTRACT, Modifier.PUBLIC);

            // 添加注释
            if (noteMap != null) {
                builder.addJavadoc("传递实体参数：\n");
                for (Map.Entry<String, String> note : noteMap.entrySet()) {
                    // 循环添加注解
                    builder.addJavadoc(note.getKey() + " : " + note.getValue() + "  --  \n");
                }
            }

            //方法注解
//            List<AnnotationSpec> l_a = getAnnotationMirrors2AnnotationSpecList(methodSymbol.getAnnotationMirrors(),
//                    ignoreAnnotation, isRest, serviceName);


            Attribute.Compound c = null;
            for (Attribute.Compound one_annotation : methodSymbol.getAnnotationMirrors()) {
                if (one_annotation.type.toString().contains("Exposes")) {
                    for(Map.Entry<Symbol.MethodSymbol, Attribute> m :  one_annotation.getElementValues().entrySet()){
                        for(Attribute a : ((Attribute.Array)m.getValue()).values){
                            Attribute.Compound compound = (Attribute.Compound) a.getValue();
                            for (Pair<Symbol.MethodSymbol, Attribute> one : compound.values) {
                                if (one.fst.toString().contains("type") ) {
                                    if(expose.type().name().toString().equals(one.snd.getValue().toString())){
                                        c = compound;
                                    }
                                }
                            }
                        }
                    }
                }else if(one_annotation.type.toString().contains("Expose")){
                    c = one_annotation;
                }
            }

            if(c == null){
                return null;
            }
            List<AnnotationSpec> m_a = getAnnotationMirrors2AnnotationSpecList(c, expose);

            //builder.addAnnotations(l_a);
            builder.addAnnotations(m_a);

            // 存在dto
            if (dtoClassName != null) {
                // 转化dto参数
                ParameterSpec.Builder namePram = ParameterSpec.builder(dtoClassName, "dto");
                // RequestBody 注解自动加入
                AnnotationSpec.Builder annotationSpec = AnnotationSpec.builder(ClassName.get("org.springframework.web.bind.annotation", "RequestBody"));
                // 添加
                namePram.addAnnotation(annotationSpec.build());
                // 添加入参数
                builder.addParameter(namePram.build());
            } else {
                // 参数
                // 字段集
                for (Symbol.VarSymbol one : parameters) {
                    SecurityData securityData = one.getAnnotation(SecurityData.class);
                    if (securityData == null) {
                        // 字段注解
                        TypeName paramsType = ClassName.get(one.type);
                        ParameterSpec.Builder namePram = ParameterSpec.builder(paramsType, one.name.toString());
                        List<AnnotationSpec> list = getAnnotationMirrors2AnnotationSpecList(one.getAnnotationMirrors(),
                                ignoreAnnotation, isRest, serviceName);
                        namePram.addAnnotations(list);
                        builder.addParameter(namePram.build());
                    }
                }
            }
            return builder.build();
        }

        return null;

    }


    /**
     * 请确保 annotationMirrors 从 getAnnotationMirrors() 获取到
     * getAnnotationMirrors()转换AnnotationSpecList
     * 注解     参数         数值
     * symbol.getParameters().get(0).getAnnotationMirrors().get(0).values.get(2).snd.type
     */
    List<AnnotationSpec> getAnnotationMirrors2AnnotationSpecList(List<Attribute.Compound> annotationMirrors,
                                                                 String[] ignoreAnnotation,
                                                                 boolean isRest,
                                                                 String serviceName) {
        List<AnnotationSpec> annotationSpecs = new ArrayList<>();
        boolean isService2RestController = false;
        boolean isService2 = false;
        for (Attribute.Compound one_annotation : annotationMirrors) {
            ClassName annotation;



            if (one_annotation.type.toString().contains("Service2RestController")) {
                if (!isRest) {
                    continue;
                }
                isService2RestController = true;
                isService2 = true;
                annotation = ClassName.get("org.springframework.web.bind.annotation", "RequestMapping");
            } else if (one_annotation.type.toString().contains("Service2FeignClient")) {
                if (isRest) {
                    continue;
                }
                isService2 = true;
                annotation = ClassName.get("org.springframework.cloud.openfeign", "FeignClient");
            } else {
                annotation = (ClassName) ClassName.get(one_annotation.type);
            }

            // 是否是忽略的注解
            if (isContainsArray(one_annotation.type.toString(), ignoreAnnotation, false)) {
                continue;
            }

            // 设置 类型
            AnnotationSpec.Builder annotationSpec = AnnotationSpec.builder(annotation);
            //dealMappingAnnotation(one_annotation);

            // 循环值
            for (Pair<Symbol.MethodSymbol, Attribute> one : one_annotation.values) {

                if (one.fst.name.toString().contains("ignorePrefixAnnotation")) {
                    continue;
                }

                if (one.snd.type.toString().contains("Enum")) {
                    annotationSpec.addMember(one.fst.name.toString(), "$L", one.snd);
                } else
                    // 设置值
                    if (one.snd.type.toString().endsWith("String")) {
                        annotationSpec.addMember(one.fst.name.toString(), "$S", one.snd.getValue().toString());
                    } else if (one.snd.getValue().getClass().toString().endsWith("List")) {
                        List<Object> vals = (List<Object>) one.snd.getValue();
                        for (Object o : vals) {
                            annotationSpec.addMember(one.fst.name.toString(), "$L", o);
                        }
                    } else if (one.snd.type.toString().startsWith("java.lang.Class<")) {
                        annotationSpec.addMember(one.fst.name.toString(), "$L", one.snd.getValue() + ".class");
                    } else {
                        annotationSpec.addMember(one.fst.name.toString(), "$L", one.snd.getValue());
                    }
            }


            // 添加保存
            annotationSpecs.add(annotationSpec.build());
        }
        if (isService2RestController) {
            AnnotationSpec.Builder annotationSpec = AnnotationSpec.builder(ClassName.get("org.springframework.web.bind.annotation", "RestController"));
            annotationSpecs.add(annotationSpec.build());
        }
        if (isService2) {
            AnnotationSpec.Builder annotationSpec = AnnotationSpec.builder(ClassName.get("org.springframework.boot.autoconfigure.condition", "ConditionalOnExpression"));
            if (isRest) {
                annotationSpec.addMember("value", "$S", "'${spring.application.name}'=='" + serviceName + "'");
            } else {
                annotationSpec.addMember("value", "$S", "'${spring.application.name}'!='" + serviceName + "'");
            }
            annotationSpecs.add(annotationSpec.build());
        }

        return annotationSpecs;
    }


    List<AnnotationSpec> getAnnotationMirrors2AnnotationSpecList( Attribute.Compound expose,  Expose exposeA) {


        List<AnnotationSpec> annotationSpecs = new ArrayList<>();
        boolean isExistProduces = false;
        // 根据 expose 生成 暴露接口 requestMapping
        boolean isExistRBAC = false;
        AnnotationSpec.Builder mappingSpec = AnnotationSpec.builder(ClassName.get("org.springframework.web.bind.annotation", "RequestMapping"));
        AnnotationSpec.Builder RBACSpec = AnnotationSpec.builder(ClassName.get(
                "com.integration.maven.service2controllerProcessor.annotation", "RBAC"));


         // 循环值
        for (Pair<Symbol.MethodSymbol, Attribute> one : expose.values) {
            if (one.fst.toString().contains("type") ) {
                continue;
            }
            if ( one.fst.toString().contains("menu")) {
                isExistRBAC =true;
                RBACSpec.addMember("menu", "$L", one.snd);
                continue;
            }
            if (one.fst.toString().contains("desc")) {
                isExistRBAC =true;
                RBACSpec.addMember("name", "$S", one.snd.getValue());
                continue;
            }

            // Mapping 处理
            if (one.fst.toString().contains("value")) {

                Object[] split = one.snd.getValue().toString().split(",");
                String api = exposeA.type().name().toString();
                String sb = "";
                for (int i = 0; i < split.length; i++) {
                    split[i] = split[i].toString().replace("\"", "");
                    if (!String.valueOf(split[i]).startsWith("/")) {
                        split[i] = "/" + split[i];
                    }
                    if (i != 0) {
                        sb += ",";
                    }
                    sb += "\"" + "/" +  api + split[i] + "\"";
                }

                mappingSpec.addMember(one.fst.name.toString(), "$L", "{" + sb + "}");
                continue;
            }
            if (one.fst.toString().contains("produces")) {
                isExistProduces = true;
                boolean isExistJson = false;
                // 处理
                String[] split = one.snd.getValue().toString().split(",");
                String sb = "";
                for (int i = 0; i < split.length; i++) {
                    split[i] = split[i].toString().replace("\"", "");
                    if (i != 0) {
                        sb += ",";
                    }
                    if (split[i].contains("application/json;charset=UTF-8")) {
                        isExistJson = true;
                    }
                    sb += "\"" + split[i] + "\"";
                }
                if (!isExistJson) {
                    sb += ",\"application/json;charset=UTF-8\"";
                }
                mappingSpec.addMember(one.fst.name.toString(), "$L", "{" + sb + "}");
                continue;
            }
            if (one.snd.type.toString().contains("Enum")) {
                mappingSpec.addMember(one.fst.name.toString(), "$L", one.snd);
            } else
                // 设置值
                if (one.snd.type.toString().endsWith("String")) {
                    mappingSpec.addMember(one.fst.name.toString(), "$S", one.snd.getValue().toString());
                } else if (one.snd.getValue().getClass().toString().endsWith("List")) {
                    List<Object> vals = (List<Object>) one.snd.getValue();
                    for (Object o : vals) {
                        mappingSpec.addMember(one.fst.name.toString(), "$L", o);
                    }
                } else if (one.snd.type.toString().startsWith("java.lang.Class<")) {
                    mappingSpec.addMember(one.fst.name.toString(), "$L", one.snd.getValue() + ".class");
                } else {
                    mappingSpec.addMember(one.fst.name.toString(), "$L", one.snd.getValue());
                }
        }

        if (!isExistProduces) {
            // 手动添加
            mappingSpec.addMember("produces", "$L", "{ \"application/json;charset=UTF-8\"}");
        }

        if(isExistRBAC){
            annotationSpecs.add(RBACSpec.build());
        }
        // 添加保存
        annotationSpecs.add(mappingSpec.build());

        return annotationSpecs;
    }

    /**
     * 实现功能描述：  注解是否需要剔除
     *
     * @param a          当前注解
     * @param arr        需要剔除的列表
     * @param defaultVal 默认值
     */
    private boolean isContainsArray(String a, String[] arr, boolean defaultVal) {
        // 默认移除 @Dto  这个注解
        if (a.contains("Dto")) {
            return true;
        }
        if (a.contains("Expose")) {
            return true;
        }
        if (a.contains("Mapping")) {
            return true;
        }
        // 不存在返回默认值
        if (arr == null || arr.length == 0) {
            return defaultVal;
        }
        // 判断是否存在剔除列表中
        for (String s : arr) {
            // 存在返回
            if (a.contains(s)) {
                return true;
            }
        }
        return defaultVal;
    }


    // get方法
    private Name getMethodName(Name name) {
        String s = name.toString();
        return names.fromString("get" + s.substring(0, 1).toUpperCase() + s.substring(1, name.length()));
    }


    /**
     * 将unicode字符串转为正常字符串
     *
     * @param str unicode字符串（比如"\u67e5\u8be2\u6210\u529f"）
     * @return 转换后的字符串（比如"查询成功"）
     */
    private static String convertUnicodeToCh(String str) {
        Pattern pattern = Pattern.compile("(\\\\u(\\w{4}))");
        Matcher matcher = pattern.matcher(str);

        // 迭代，将str中的所有unicode转换为正常字符
        while (matcher.find()) {
            String unicodeFull = matcher.group(1); // 匹配出的每个字的unicode，比如\u67e5
            String unicodeNum = matcher.group(2); // 匹配出每个字的数字，比如\u67e5，会匹配出67e5

            // 将匹配出的数字按照16进制转换为10进制，转换为char类型，就是对应的正常字符了
            char singleChar = (char) Integer.parseInt(unicodeNum, 16);

            // 替换原始字符串中的unicode码
            str = str.replace(unicodeFull, singleChar + "");
        }
        return str;
    }


    /**
     * 将字符串的编码格式转换为utf-8
     *
     * @param str
     * @return Name = new
     * String(Name.getBytes("ISO-8859-1"), "utf-8");
     */
    public static String toUTF8(String str) {
        if (isEmpty(str)) {
            return "";
        }
        try {
            if (str.equals(new String(str.getBytes("GB2312"), "GB2312"))) {
                str = new String(str.getBytes("GB2312"), "utf-8");
                return str;
            }
        } catch (Exception exception) {
        }
        try {
            if (str.equals(new String(str.getBytes("ISO-8859-1"), "ISO-8859-1"))) {
                str = new String(str.getBytes("ISO-8859-1"), "utf-8");
                return str;
            }
        } catch (Exception exception1) {
        }
        try {
            if (str.equals(new String(str.getBytes("GBK"), "GBK"))) {
                str = new String(str.getBytes("GBK"), "utf-8");
                return str;
            }
        } catch (Exception exception3) {
        }
        return str;
    }

    /**
     * 判断是否为空
     *
     * @param str
     * @return
     */
    public static boolean isEmpty(String str) {
        // 如果字符串不为null，去除空格后值不与空字符串相等的话，证明字符串有实质性的内容
        if (str != null && !str.trim().isEmpty()) {
            return false;// 不为空
        }
        return true;// 为空
    }


}
